package com.dnjn.happiness.auth.controller;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.api.common.Constants;
import com.dnjn.happiness.auth.config.DingTalkConfig;
import com.dnjn.happiness.auth.handler.DingTalkConfigSign;
import com.dnjn.happiness.auth.handler.DingTalkHandler;
import com.dnjn.happiness.auth.service.IDingTalkService;
import com.dnjn.happiness.common.core.constant.SecurityConstants;
import com.dnjn.happiness.common.core.domain.R;
import com.dnjn.happiness.common.core.enums.UserStatus;
import com.dnjn.happiness.common.core.exception.ServiceException;
import com.dnjn.happiness.common.core.utils.MessageUtils;
import com.dnjn.happiness.common.core.utils.ServletUtils;
import com.dnjn.happiness.common.core.utils.StringUtils;
import com.dnjn.happiness.common.core.web.domain.AjaxResult;
import com.dnjn.happiness.common.security.service.TokenService;
import com.dnjn.happiness.system.api.RemoteUserService;
import com.dnjn.happiness.system.api.domain.SysUser;
import com.dnjn.happiness.system.api.model.LoginUser;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
 * @author ywj
 */
@Slf4j
@RestController
@RequestMapping("/dingtalk")
public class DingTalkController {

    public static final String IAM_SESSION_TOKEN = "IAM_SESSION_TOKEN";

    public static final String NONCE_STR = "dn_dingTalk";
    @Data
    public static class SignVo implements Serializable {
        private String url;
    }

    @Autowired
    private IDingTalkService dingTalkService;

    @Autowired
    private DingTalkConfig config;

    @Autowired
    private RemoteUserService userService;

    @Autowired
    private TokenService tokenService;
    @Autowired
    private DingTalkHandler dingTalkHandler;

    @GetMapping("/corpId")
    public AjaxResult getCorpId() {
        return AjaxResult.success().put("corpId", config.getCorpId());
    }

    @PostMapping(value = "/callback")
    public Object dingCallback(
            @RequestParam(value = "signature") String signature,
            @RequestParam(value = "timestamp") Long timestamp,
            @RequestParam(value = "nonce") String nonce,
            @RequestBody(required = false) JSONObject body
    ) {
        return dingTalkService.handleDingTalkCallback(signature, timestamp, nonce, body);
    }
   /* @GetMapping("/getToken")
    public AjaxResult getToken() {
        String token = dingTalkService.getAccessToken(appConfig.getAppKey(), appConfig.getAppSecret());
        return AjaxResult.success(token);
    }
    */

    @PostMapping("configSign")
    public AjaxResult configSign(@RequestBody SignVo signVo) throws Exception {
        String url = signVo.getUrl();
        log.info("dingtalk sign url : {}", url);
        String accessToken = dingTalkHandler.getAccessToken();
        String jsapiTicket = dingTalkHandler.getJsapiTicket(accessToken);

//        String accessToken = getAccessToken(config.getClientId(),config.getClientSecret());
        long timestamp = System.currentTimeMillis();
        String sign = DingTalkConfigSign.sign(jsapiTicket, NONCE_STR, timestamp, url);

        return AjaxResult.success()
                .put("sign", sign)
                .put("corpId", config.getCorpId())
                .put("agentId", config.getAgentId())
                .put("timeStamp", timestamp)
                .put("nonceStr", NONCE_STR)
                //.put("expireIn", resp1.getBody().getExpireIn())
                .put("signature", sign)
                ;
    }

    /**
     * 根据免登授权码, 获取登录用户身份
     *
     * @param
     * @return
     */
    @GetMapping("/login")
    public AjaxResult login(@RequestParam(value = "anthCode") String anthCode) {
        AjaxResult ajax = new AjaxResult();
//        String token = dingTalkService.getUserInfo(anthCode);
//        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    @GetMapping("/test")
    public AjaxResult test() {
        String url = "http://ip:port/IAM/token.action?operate=getToken";
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("appSn", "");
        jsonParam.put("appSecret", "");
        Object result = doPost(url, jsonParam);
        JSONObject jsons = JSONObject.parseObject(result.toString());
        String token = jsons.getString("access_token");
        String expires_in = jsons.getString("expires_in");
        return AjaxResult.success(result);
    }


    /**
     * OAUTH单点认证 不适用JDK集成; jingkosolar IAM
     */
    @GetMapping("/oauthLogin")
    public AjaxResult oauthLogin(String code) {

        String iamUrl = config.getIamUrl();
        String clientId = config.getIamClientId();
        String clientSecret = config.getIamClientSecret();
        HttpServletRequest req = ServletUtils.getRequest();
        HttpServletResponse resp = ServletUtils.getResponse();
        //从session中获取uid,如果没有说明未登录，需要进行登录
        String uid = (String) req.getSession().getAttribute("IAM_SESSION_TOKEN");
        if (null == uid || "".equals(uid.trim())) {
            //为登录的情况
//            String code = req.getParameter("code");
            log.warn("code:" + code);
            //没有accessToken，去认证中心里请求
            if (null == code || "".equals(code.trim())) {
                //构造authorize URL
                String url =  /* iamUrl + "/IAM/oauth/authorize?client_id=" + clientId;*/
                        StringUtils.format("{}/IAM/oauth/authorize?client_id={}&redirect_uri={}", iamUrl, clientId, config.getIamRedirectUrl());
//                try {
//                    resp.sendRedirect(url);
//                    return null;
//                } catch (IOException e) {
//                    e.printStackTrace();
//                    log.error("重定向失败" + e.getMessage());
//                }

                return AjaxResult.success().put("redirect", url);
            }
            //根据code获取accessToken的过程
            String accessToken = null;
            Map<String, Object> params = new HashMap<>();
            params.put("code", code);
            params.put("client_id", clientId);
            params.put("client_secret", clientSecret);
            log.warn("accessToken in: {}", JSON.toJSONString(params));
            String result = HttpUtil.post(iamUrl + "/IAM/oauth/token", params);
            if (result != null && !"".equals(result.trim())) {
                //解析json
                JSONObject json = JSONObject.parseObject(result);
                log.warn("accessToken result: " + json.toJSONString());
                accessToken = json.getString("access_token");
            }

            //根据SessionToken获取用户信息（目前获取到的就是账号）
            String userInfo = "";
            String token = null;
            if (accessToken != null && !"".equals(accessToken)) {
                //从服务器上获取到了accessToken 开始获取用户信息了
                params = new HashMap<>();
                params.put("access_token", accessToken);
                result = HttpUtil.post(iamUrl + "/IAM/oauth/getUserInfo", params);
                log.warn("userInfo result: " + result);
                if (result != null && !"".equals(result.trim())) {
                    //解析
                    JSONObject json = JSONObject.parseObject(result);
                    //获取用户唯一标识，换取本地token
                    token = createToken(json);

                    userInfo = json.toString();
                    log.warn("userInfo:" + userInfo);

                    return AjaxResult.success().put(Constants.TOKEN, token);
                }
            }
        }
        return AjaxResult.error();
    }

    @Deprecated
    public String getAccessToken(String appKey, String appSecret) {
        //String url = "/v1.0/oauth2/accessToken HTTP/1.1";
        String url = "/v1.0/oauth2/accessToken";
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("appKey", appKey);
        jsonParam.put("appSecret", appSecret);
        Object result = doPost(url, jsonParam);
        String access_token = "";
        JSONObject jsons = JSONObject.parseObject(result.toString());
        String expires_in = jsons.getString("expires_in");
        if (StringUtils.isNotEmpty(expires_in) && Integer.parseInt(expires_in) == 7200) {
            //ok
            access_token = jsons.getString("access_token");
            log.info("出错获取token失败!");
        }
        return access_token;
    }

    public String doPost(String url, JSONObject jsonParam) {
        InputStream instreams = null;
        String urlPath = config.getApi() + url;
        HttpPost httpRequst = new HttpPost(urlPath);// 创建HttpPost对象
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try {
            StringEntity se = new StringEntity(jsonParam.toString(), "utf-8");
            se.setContentType("application/json");
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "UTF-8"));
            httpRequst.setEntity(se);
            HttpResponse httpResponse = new DefaultHttpClient().execute(httpRequst);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity httpEntity = httpResponse.getEntity();
                if (httpEntity != null) {
                    instreams = httpEntity.getContent();
                    in = new BufferedReader(new InputStreamReader(instreams, StandardCharsets.UTF_8));
                    String line;
                    while ((line = in.readLine()) != null) {
                        result.append(line);
                    }
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                log.error("调用in.close Exception, url=" + url + "");
            }
        }
        return result.toString();
    }

    public void getToken(String appKey, String appSecret) {
        String url = "appKey=" + appKey + "&appSecret=" + appSecret;
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(url);
        PrintWriter out = null;
        BufferedReader reader = null;
        String token;
        StringBuilder result = new StringBuilder();
        try {
            HttpResponse response = client.execute(request);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = entity.getContent();
                reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }

                JSONObject jsonObject = new JSONObject(Integer.parseInt(result.toString()));
                token = jsonObject.getString("access_token");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    private String createToken(JSONObject json) {
        //假设返回用户信息id为工号,通过工号查询用户信息，封装token返回
        String id = (String) json.get("uid");
        SysUser sysUser = null;
        R<SysUser> result = userService.getUserByUnId(id, SecurityConstants.INNER);
        if(StringUtils.isNotNull(result) && StringUtils.isNotNull(result.getData())){
            sysUser = result.getData();
        }
        if (null != sysUser) {
             if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus()))
            {
                log.info("登录用户：{} 已被停用.", sysUser.getUserName());
                throw new ServiceException(MessageUtils.message("user.blocked"));
            }else {
                 LoginUser loginUser = new LoginUser();
                 loginUser.setUser(sysUser);
                 loginUser.setUserid(sysUser.getUserId());
                 loginUser.setDeptId(sysUser.getDeptId());
//        recordLoginInfo(loginUser.getUserId());
                 // 生成token
                 return (String) tokenService.createToken(loginUser).get("access_token");
             }
        } else {
            throw new RuntimeException("没有该账号:"+id);
        }

    }
}










